﻿#pragma once
#include "DirectX/stdafx.h"

#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif

struct fRECT
{
public:
	float	top,left,bottom,right;
};

struct SimpleVertex 
{
	float x, y,z; 
	D3DXCOLOR color;
	SimpleVertex(){}
	SimpleVertex(float x_,float y_,float z_,D3DXCOLOR &color_)
	{
		x=x_;
		y=y_;
		z=z_;
		color=color_;
	}
  
};

#ifndef LIGHT_ENABLE
	struct CUSTOMVERTEX
	{
		CUSTOMVERTEX(){}
		CUSTOMVERTEX(float x_,float y_,float z_,float tu_,float tv_)
		{
			x	=	x_;
			y	=	y_;
			z	=	z_;

			tu	=	tu_;
			tv	=	tv_;
		}
		CUSTOMVERTEX(const D3DXVECTOR3 &Vec3, float tu_, float tv_)
		{
			x	=	Vec3.x;
			y	=	Vec3.y;
			z	=	Vec3.z;

			tu	=	tu_;
			tv	=	tv_;
		}
		float x,y,z,tu,tv;
	};
	#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)

#else

	struct CUSTOMVERTEX
	{
		CUSTOMVERTEX(){}
		CUSTOMVERTEX(float x_,float y_,float z_,float tu_,float tv_,const D3DXVECTOR3 &n)
		{
			x	=	x_;
			y	=	y_;
			z	=	z_;

			tu	=	tu_;
			tv	=	tv_;

			n0	=	n.x;
			n1	=	n.y;
			n2	=	n.z;
		}
		CUSTOMVERTEX(const D3DXVECTOR3 &Vec3, float tu_, float tv_,const D3DXVECTOR3 &Normal)
		{
			x	=	Vec3.x;
			y	=	Vec3.y;
			z	=	Vec3.z;

			tu	=	tu_;
			tv	=	tv_;

			n0	=	Normal.x;
			n1	=	Normal.y;
			n2	=	Normal.z;
		}
		float x,y,z,n0,n1,n2,tu,tv;
	};
	#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)

#endif


class D3DCamera
{
private:
	time_t				Time_Move,
						X_Speed,
						Easing;

	D3DXMATRIX			MatrixProjection,
						View;

	float				Distance,
						Height,
						Width;
						
public:
	D3DXVECTOR3			CamPos,
						ViewPos,
						AnglePos;

	D3DCamera(){Time_Move = 150;X_Speed = 0; Easing = 80;}
	D3DCamera(	D3DXVECTOR3 CamPos_,
				D3DXVECTOR3 ViewPos_,
				D3DXVECTOR3 AnglePos_,
				int 		easing,
				float		Height_,
				float 		Width_)
	{
		Distance		=	10000;
		Width			=	16;
		Height			=	9;
		Easing			=	easing;
		Time_Move		=	250;
		X_Speed			=	0;
		CamPos			=	CamPos_;
		ViewPos			=	ViewPos_;
		AnglePos		=	AnglePos_;
		Height			=	Height_;
		Width			=	Width_;
	}

	void ApplyProjection(LPDIRECT3DDEVICE9 &pd3dDevice)
	{
		D3DXMatrixPerspectiveFovLH(	&MatrixProjection,
									D3DX_PI/4,
									Width / Height,
									1.0f,
									Distance);
		pd3dDevice->SetTransform(D3DTS_PROJECTION, &MatrixProjection);
	}
	void ApplyView(LPDIRECT3DDEVICE9 &pd3dDevice)
	{
		D3DXMatrixLookAtLH(	&View, 
							&CamPos,
							&ViewPos,
							&AnglePos);
		pd3dDevice->SetTransform(D3DTS_VIEW, &View);
	}
	void MouseWheel(bool Z_Minus)
	{
		Time_Move	=	clock()+471;

		if(Z_Minus)
		{
			if(X_Speed < 0)	X_Speed = 1;
			else			X_Speed++;

		}
		else
		{
			if(X_Speed > 0)	X_Speed = -1;
			else			X_Speed--;
		}

		if(X_Speed > 5)		X_Speed = 5;
		if(X_Speed < -5)	X_Speed = -5;

		if(X_Speed == 0)
			Time_Move = clock() - 1;
	}
	bool CameraCubMove()
	{
		if(Time_Move < clock() || X_Speed == 0) { X_Speed = 0; return false;}



		CamPos.z += (float)sin((double)(Time_Move - clock()) / 1500 ) * X_Speed ;

		return true;
	}
};
class D3DXText
{
private:
	vector<LPDIRECT3DTEXTURE9>		StaticTextures;
	LPD3DXSPRITE					Sprite;

	D3DXMATRIX						MatrixWorld,
									MatrixView,
									MatrixTransform;

	D3DXVECTOR3						CamPos,
									ViewPos,
									AnglePos;

	float							x,
									y;

	WCHAR							text[1024];

	D3DCOLOR						Color;

	void LoadFromFile(LPDIRECT3DDEVICE9 pd3dDevice, vector<LPCWSTR> Textures,WCHAR *Color)
	{
		for(UINT q=0; q<StaticTextures.size(); q++)
			StaticTextures[q]->Release();

		StaticTextures.clear();
		StaticTextures.resize(Textures.size());

		for(UINT q=0; q<Textures.size(); q++)
		{
			WCHAR Location[512];
			if(q < 10)	wcscpy_s(Location, L"DirectX\\Digit\\");
			else		wcscpy_s(Location, L"DirectX\\Font\\");
			wcscat_s(Location, Color);
			wcscat_s(Location, L"\\");
			wcscat_s(Location, Textures[q]);
			D3DXCreateTextureFromFile(pd3dDevice, Location, &StaticTextures[q]);
		}
	}
	LPWSTR UpRegister(LPCWSTR text)
	{
		WCHAR result[512];
		int size = wcslen(text);
		for(UINT q=0; q<size; q++)
		{
			if(text[q] <= L'z' && text[q] >= L'a')	result[q] =	L'A' + (text[q] - L'a');
			else									result[q] = text[q];
		}
		result[size] = '\0';
		return result;
	}
	void ApplyMatrixes()
	{
		D3DXMatrixLookAtLH		(&MatrixView, 	&CamPos,
												&ViewPos,
												&AnglePos);

		Sprite->SetWorldViewLH	(&MatrixWorld,	&MatrixView);


		D3DXVECTOR2				dir(1, 1);
		D3DXVec2Normalize(&dir, &dir);

		D3DXMatrixTransformation2D(	&MatrixTransform, 
									NULL,
									-10,
									&dir,
									NULL,
									NULL,
									NULL);
		Sprite->SetTransform(&MatrixTransform);
	}

public:
	D3DXText(){}
	D3DXText(LPDIRECT3DDEVICE9 pd3dDevice, WCHAR *Color_)
	{
		CamPos					=	D3DXVECTOR3(0.0f, 0.0f, 1.0f);
		ViewPos					=	D3DXVECTOR3(0.0f, 0.0f, 1.0f);
		AnglePos				=	D3DXVECTOR3(0.0f, 1.0f, 0.0f);
		vector<LPCWSTR>			Textures;
		Color					=	D3DCOLOR_XRGB(150,150,150);
		//Digit
		for(UINT q=0; q<10; q++)
		{
			WCHAR				buf[10][512];
			wcscpy_s			(buf[q], L"0");
								buf[q][0]	+=	q;
			wcscat_s			(buf[q], L".png");
			Textures.push_back	(buf[q]);
		}

		//Font
		for(UINT q=0; q<26; q++)
		{
			WCHAR				buf[26][512];
			wcscpy_s			(buf[q],L"A");
								buf[q][0]	+=	q;
			wcscat_s			(buf[q],L".png");
			Textures.push_back	(buf[q]);
		}

		//Any
		Textures.push_back(L"Left.png");
		Textures.push_back(L"Up.png");
		Textures.push_back(L"Right.png");
		Textures.push_back(L"Down.png");
		Textures.push_back(L"!.png");
		Textures.push_back(L"What.png");
		
		D3DXCreateSprite		(pd3dDevice, &Sprite);
		LoadFromFile			(pd3dDevice, Textures, Color_);
	}
	
	unsigned int Draw()
	{
		UINT bugs	=	0;
		UINT size	=	wcslen(text);

		wcscpy_s(text,	UpRegister(text));		

		ApplyMatrixes();
		Sprite->Begin			(D3DXSPRITE_ALPHABLEND);
		
		for(UINT q=0, un_q=0, un_x=0, i_str=0; q<size; q++)
		{
			UINT index	=	(int)text[q]+10-(int)L'A';
			if(text[q] <= L'9')					index = text[q] - L'0';
			if(text[q] == L'◄')					index = 26+10+0;
			if(text[q] == L'▲')					index = 26+10+1;
			if(text[q] == L'►')					index = 26+10+2;
			if(text[q] == L'▼')					index = 26+10+3;
			if(text[q] == L'!')					index = 26+10+4;
			if(text[q] == L'?')					index = 26+10+5;
			if(text[q] == L'\n')				{bugs--; y += 62; un_q = q; un_x += 32;}
			if(index >= StaticTextures.size())	{bugs++; continue;}
			

			Sprite->Draw		(StaticTextures[index], NULL, NULL, &D3DXVECTOR3(x + (q-un_q)*32 - un_x, y, 0.0f), Color);
		}

		Sprite->End();
		return bugs;
	}
	void	Cat(LPCWSTR text_)
	{
		wcscat_s(text, text_);
	}
	void	Cpy(LPCWSTR text_)
	{
		wcscpy_s(text, text_);
	}
	void	Cpy(float f_buffer)
	{
		std::wstringstream stream;
		stream << f_buffer;
		stream.getline(text, 1024);
	}
	void	Cpy(int i_buffer)
	{
		_itow_s(i_buffer, text, 10); 
	}
	void	Cpy(double d_buffer)
	{
		std::wstringstream stream;
		stream << d_buffer;
		stream.getline(text, 1024);
	}
	void	Cpy(char* c_buffer)
	{
		std::wstringstream stream;
		stream << c_buffer;
		stream.getline(text, 1024);
	}
	void	Clear()
	{
		wcscpy_s(text, L"");
	}
	LPWSTR	getText()
	{
		WCHAR result[512];
		wcscpy_s(result, text);
		return result;
	}
	void	SetX(float x_)				{x = x_;}
	void	SetY(float y_)				{y = y_;}
	void	SetColor(D3DCOLOR NewColor)	{Color = NewColor;}
	D3DCOLOR GetColor()					{return Color;}

	static int		Colorito(bool SIN, UINT Slow, UINT Sleep)
	{
		Sleep%=256;
		if(SIN)		return (int) abs( sin( (double)clock() / Slow) * (256-Sleep)) + Sleep;
		else		return (int) abs( cos( (double)clock() / Slow) * (256-Sleep)) + Sleep;
	}
	static double	Move(bool SIN,UINT Slow, float R, float Center)
	{
		if(SIN)		return abs(sin((double)clock()/Slow)*R+Center);
		else		return abs(cos((double)clock()/Slow)*R+Center);
	}

	~D3DXText()
	{
		ZeroMemory(text,sizeof(text));
		for(UINT q=0; q<StaticTextures.size(); q++)
		{
			if(StaticTextures[q] != NULL)
			{
				//StaticTextures[q]->Release();
				StaticTextures[q] = NULL;
			}
		}
		StaticTextures.clear();
		//Sprite->Release();
		Sprite	=	NULL;
	}
};
#define Colorito	D3DXText::Colorito
#define Move		D3DXText::Move

#include "Math.h"
		using namespace Math;
class D3DRectangle
{
protected:
	//  x1 y1 ------------------------- x1 y2
	//    |                               |
	//    |                               |
	//    |                               |
	//    |                               |
	//  x2 y1 ------------------------- x2 y2

	//   p1 ----------------------------- p2
	//    |                               |
	//    |                               |
	//    |                               |
	//    |                               |
	//   p4 ----------------------------- p3

	D3DXVECTOR3		p1,p2,p3,p4,
					n1,n2;
	fRECT rect;
public:
	D3DRectangle()
	{
		rect.top	= rect.left		= 0;
		rect.bottom	= rect.right	= 1;

		initNormal();
	}
	D3DRectangle(float x1_, float y1_, float z1_, float x2_, float y2_, float z2_, float z3_, float z4_)
	{

		p1.x = x1_;
		p2.x = x2_;

		p1.y = y1_;
		p2.y = y2_;

		p1.z = z1_;
		p2.z = z2_;
		p3.z = z3_;
		p4.z = z4_;

		p3.x = p2.x;
		p3.y = p1.y;
		p4.x = p1.x;
		p4.y = p2.y;


		rect.top	= rect.left		= 0;
		rect.bottom	= rect.right	= 1;

		initNormal();
	}
	D3DRectangle(D3DXVECTOR3 &p1_, D3DXVECTOR3 &p2_, D3DXVECTOR3 &p3_, D3DXVECTOR3 &p4_)
	{
		p1 = p1_;
		p2 = p2_;
		p3 = p3_;
		p4 = p4_;
		rect.top	= rect.left		= 0;
		rect.bottom	= rect.right	= 1;

		initNormal();
		
	}

	D3DRectangle(D3DXVECTOR3 &p1_, D3DXVECTOR3 &p2_, D3DXVECTOR3 &p3_, D3DXVECTOR3 &p4_, fRECT &zone)
	{
		p1 = p1_;
		p2 = p2_;
		p3 = p3_;
		p4 = p4_;
		rect = zone;

		initNormal();
	}

	CUSTOMVERTEX* init()
	{
		CUSTOMVERTEX *result=new CUSTOMVERTEX[6];
		#ifndef LIGHT_ENABLE		
		result[0] = CUSTOMVERTEX(p1, (float)rect.left,  (float)rect.top		);
		result[1] = CUSTOMVERTEX(p2, (float)rect.right, (float)rect.top		);
		result[2] = CUSTOMVERTEX(p3, (float)rect.right, (float)rect.bottom	);
		result[3] = CUSTOMVERTEX(p1, (float)rect.left,  (float)rect.top		);
		result[4] = CUSTOMVERTEX(p3, (float)rect.right, (float)rect.bottom	);
		result[5] = CUSTOMVERTEX(p4, (float)rect.left, (float)rect.bottom	);
		#else

		result[0] = CUSTOMVERTEX(p1, (float)rect.left,  (float)rect.top,		n1);
		result[1] = CUSTOMVERTEX(p2, (float)rect.right, (float)rect.top,		n1);
		result[2] = CUSTOMVERTEX(p3, (float)rect.right, (float)rect.bottom,		n1);
		result[3] = CUSTOMVERTEX(p1, (float)rect.left,  (float)rect.top,		n2);
		result[4] = CUSTOMVERTEX(p3, (float)rect.right, (float)rect.bottom,		n2);
		result[5] = CUSTOMVERTEX(p4, (float)rect.left, (float)rect.bottom,		n2);
		#endif
		
		return result;
	}

	void initNormal()
	{
		D3DXVECTOR3 u = D3DXVECTOR3(p3.x, p1.y, p2.z) - D3DXVECTOR3(p1.x, p1.y, p1.z);
		D3DXVECTOR3 v = D3DXVECTOR3(p3.x, p3.y, p3.z) - D3DXVECTOR3(p1.x, p1.y, p1.z);

		D3DXVec3Cross		(&n1, &u, &v);
		D3DXVec3Normalize	(&n1, &n1);
		n1 *= -1;

		u = D3DXVECTOR3(p3.x, p1.y, p4.z) - D3DXVECTOR3(p1.x, p1.y, p1.z);
		v = D3DXVECTOR3(p3.x, p3.y, p3.z) - D3DXVECTOR3(p1.x, p1.y, p1.z);

		D3DXVec3Cross		(&n2, &u, &v);
		D3DXVec3Normalize	(&n2, &n2);
		n2 *= -1;
	}

	float getBestUp()
	{
		if(p1.y>p2.y)
			return p1.y;
		else
			return p2.y;
	}
	float getBestDown()
	{
		if(p1.y>p2.y)
			return p2.y;
		else
			return p1.y;
	}

	float getx1(){return p1.x;}
	float gety1(){return p1.y;}
	float getz1(){return p1.z;}
	float getx2(){return p2.x;}
	float gety2(){return p2.y;}
	float getz2(){return p2.z;}
	float getz3(){return p3.z;}
	float getz4(){return p4.z;}


	pair<bool, int> Select(D3DXVECTOR3 &pos, D3DXVECTOR3 &dir)
	{
		float				Distance	=	200000.0f;

		D3DXVECTOR3			MousePos;

		bool				Result_1	=	false,
							Result_2	=	false;


		

		Result_1	=	 D3DXIntersectTri	(	&p1, 
												&p2,
												&p3,
												&pos,
												&dir,
												0,
												0,
												&Distance);
		if(Result_1)
			MousePos = Math::GetPoint_Vector_Length(pos, dir, Distance);

		Result_2	=	 D3DXIntersectTri	(	&p1, 
												&p3,
												&p4,
												&pos,
												&dir,
												0,
												0,
												&Distance);
		if(Result_2)
			MousePos = Math::GetPoint_Vector_Length(pos, dir, Distance);


		pair<bool, int> result;
		result.first = Result_1 || Result_2;
		result.second = 1;

		return result;
	}


	~D3DRectangle()
	{
		
	}
};

#include "DirectX/Direct3D_UI.h"

class DirectX
{
protected:
/*-------------------------------Private Data Base----------------------------------*/
	LPDIRECT3D9					pD3D;
	LPDIRECT3DDEVICE9			pd3dDevice;
	LPDIRECT3DSURFACE9			Surface_Monitor;
	LPDIRECT3DVERTEXBUFFER9		g_pVB;
	LPDIRECT3DINDEXBUFFER9		g_pIB;

	D3DXMATRIX					MatrixWorld,
								MatrixWorldY,
								MatrixWorldX,
								MatrixWorldZ;

	vector<LPDIRECT3DTEXTURE9>	StaticTextures;
	vector<D3DMATERIAL9>		Materials;
	vector<D3DLIGHT9>			Lights;
	vector<D3DRectangle>		Rectangles;
	vector<D3D_UI*>				UI;
	vector<D3DXText>			Text;

	D3DCamera					Camera;
	
	HINSTANCE					hInst;	

	LPDIRECTINPUT8				General_Input;
	LPDIRECTINPUTDEVICE8W		Keyboard,
								Mouse;
	DIMOUSESTATE				mouse;
	char						keyboard[256];

	D3DDISPLAYMODE				Display;
	D3DPRESENT_PARAMETERS		d3dpp;


/*---------------------------------------Timers-------------------------------------*/
	time_t						Timer1,
								Timer2;
/*----------------------------------------------------------------------------------*/
/*----------------------------------------Flags-------------------------------------*/
	bool						LightIsTurned;
/*----------------------------------------------------------------------------------*/

/*---------------------------------------Methods------------------------------------*/
	void initD3Present_Parameters(bool Windowed,int BackBufferCount,HWND Window_hWnd,UINT MultiSampleType)
	{
		ZeroMemory( &d3dpp, sizeof( d3dpp ) );
		d3dpp.Windowed					=	Windowed;
		d3dpp.SwapEffect				=	D3DSWAPEFFECT_DISCARD;
		d3dpp.BackBufferFormat			=	Display.Format;
		d3dpp.BackBufferCount			=	BackBufferCount;

		RECT Window;
		GetClientRect(Window_hWnd,&Window);
		d3dpp.BackBufferHeight			=	Window.bottom;
		d3dpp.BackBufferWidth			=	Window.right;
		d3dpp.hDeviceWindow				=	Window_hWnd;
		d3dpp.EnableAutoDepthStencil	=	true;
		d3dpp.AutoDepthStencilFormat	=	D3DFMT_D24S8;
		d3dpp.Flags						=	D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
		d3dpp.MultiSampleType			=	(D3DMULTISAMPLE_TYPE)	MultiSampleType;

		if(!Windowed)
		{
			d3dpp.FullScreen_RefreshRateInHz	=	Display.RefreshRate;
			d3dpp.BackBufferHeight				=	GetSystemMetrics(SM_CYSCREEN);
			d3dpp.BackBufferWidth				=	GetSystemMetrics(SM_CXSCREEN);
		}
	}
	void initDisplay()
	{
		pD3D->GetAdapterDisplayMode			(D3DADAPTER_DEFAULT,		&Display);
	}
	bool initD3D()
	{
		if( NULL == ( pD3D = Direct3DCreate9(D3D_SDK_VERSION)))			return false;
		return true;
	}
	bool initDirect3D(bool Light_Enable, bool Enable_Super_Light, UINT TextDetal, UINT MaxAnisotropi)
	{	
		// Create a default DirectX device
		if( FAILED( pD3D->CreateDevice		(D3DADAPTER_DEFAULT,
												D3DDEVTYPE_HAL,
												d3dpp.hDeviceWindow,
												D3DCREATE_HARDWARE_VERTEXPROCESSING,
												&d3dpp,
												&pd3dDevice)))			return false;

		pd3dDevice->SetRenderState			(D3DRS_AMBIENT,				true);
		pd3dDevice->SetRenderState			(D3DRS_SPECULARENABLE,		Enable_Super_Light);
		pd3dDevice->SetRenderState			(D3DRS_ALPHABLENDENABLE,	true);
		pd3dDevice->SetRenderState			(D3DRS_SRCBLEND,			D3DBLEND_SRCALPHA);
		pd3dDevice->SetRenderState			(D3DRS_DESTBLEND,			D3DBLEND_INVSRCALPHA);
		pd3dDevice->SetRenderState			(D3DRS_ZENABLE,				D3DZB_TRUE);
		pd3dDevice->SetRenderState			(D3DRS_CULLMODE,			D3DCULL_NONE);
		pd3dDevice->SetRenderState			(D3DRS_LIGHTING,			Light_Enable);
		

		pd3dDevice->SetTextureStageState	(0,							D3DTSS_COLORARG1,D3DTA_TEXTURE);
		pd3dDevice->SetTextureStageState	(0,							D3DTSS_COLOROP,D3DTOP_MODULATE);
		pd3dDevice->SetTextureStageState	(0,							D3DTSS_TEXTURETRANSFORMFLAGS ,D3DTTFF_COUNT3);

		pd3dDevice->SetSamplerState			(0, D3DSAMP_MAGFILTER, TextDetal);
		pd3dDevice->SetSamplerState			(0, D3DSAMP_MINFILTER, TextDetal);
		pd3dDevice->SetSamplerState			(0, D3DSAMP_MAXANISOTROPY, MaxAnisotropi);


		DirectInput8Create					(hInst,DIRECTINPUT_VERSION, IID_IDirectInput8W,(void**)&General_Input,NULL);

		General_Input->CreateDevice			(GUID_SysKeyboard,	  &Keyboard, NULL);
		Keyboard->SetDataFormat				(&c_dfDIKeyboard);
		Keyboard->SetCooperativeLevel		(d3dpp.hDeviceWindow, DISCL_FOREGROUND);
		Keyboard->Acquire();

		General_Input->CreateDevice			(GUID_SysMouse,		  &Mouse, NULL);
		Mouse->SetDataFormat				(&c_dfDIMouse);
		Mouse->SetCooperativeLevel			(d3dpp.hDeviceWindow, DISCL_EXCLUSIVE);
		Mouse->Acquire();

		return true;
	}
	void initD3DCamera()
	{
		Camera = *new D3DCamera(	D3DXVECTOR3(0.0f, 0.0f, -90.0f),
									D3DXVECTOR3(0.0f, 0.0f, 0.0f),
									D3DXVECTOR3(0.0f, 1.0f, 0.0f),
									80,
									d3dpp.BackBufferHeight,
									d3dpp.BackBufferWidth);
	}
	bool SetupVB()
	{
		UINT size = Rectangles.size() * 6;

		if(size == 0)
			return false;

		CUSTOMVERTEX **g_Vertices = new CUSTOMVERTEX*[Rectangles.size()];

		for(UINT q=0; q<Rectangles.size(); q++)
			g_Vertices[q] = Rectangles[q].init();

		

		if(g_pVB!=NULL) g_pVB->Release();

		pd3dDevice->CreateVertexBuffer(
			size * sizeof(CUSTOMVERTEX),
			D3DUSAGE_DYNAMIC,
			D3DFVF_CUSTOMVERTEX,
			D3DPOOL_DEFAULT,
			&g_pVB,
			NULL );

		VOID* pVertices;
		g_pVB->Lock( 0, size * sizeof(CUSTOMVERTEX), (void**)&pVertices, 0 );
		for(int q=0; q<Rectangles.size(); q++)
			memcpy( (CUSTOMVERTEX*)pVertices + q*6, g_Vertices[q], 6 * sizeof(CUSTOMVERTEX) );
		g_pVB->Unlock();

		for(int q=0; q<Rectangles.size(); q++)
			delete g_Vertices[q];

		delete []g_Vertices, g_Vertices, pVertices;

		return true;
	}
	void SetLight(UINT index_lights, D3DLIGHTTYPE Light_Type, D3DXVECTOR3 &pos, D3DXVECTOR3 &dir, float distance)
	{
		D3DLIGHT9				new_Light;

		new_Light.Position		= pos;
		new_Light.Type			= Light_Type;
		new_Light.Specular.r	= new_Light.Ambient.r		= new_Light.Diffuse.r		= 1.0f;
		new_Light.Specular.g	= new_Light.Ambient.g		= new_Light.Diffuse.g		= 1.0f;
		new_Light.Specular.b	= new_Light.Ambient.b		= new_Light.Diffuse.b		= 1.0f;
		new_Light.Specular.a	= new_Light.Ambient.a		= new_Light.Diffuse.a		= 1.0f;
	
		new_Light.Range			= distance; //Растояние

		D3DXVec3Normalize		(&dir, &dir);

		new_Light.Direction		= dir;
			
		if(Lights.size() <= index_lights)
		{
			for(UINT q=0;q < Lights.size();q++)
				Lights.push_back(*new D3DLIGHT9());

			Lights.push_back(new_Light);
			return;
		}
		Lights[index_lights] = new_Light;
	}
	void SetMaterial(UINT index_material, D3DMATERIAL9 new_Material)
	{
		if(Materials.size() <= index_material)
		{
			for(UINT q=0;q < Materials.size();q++)
			{
				Materials.push_back(*new D3DMATERIAL9());
			}
			Materials.push_back(new_Material);
		}
		Materials[index_material] = new_Material;
	}
	void SetMatrixWorld(float fx, float fy, float fz)
	{
		D3DXMatrixIdentity(&MatrixWorldY);
		D3DXMatrixIdentity(&MatrixWorldX);
		D3DXMatrixIdentity(&MatrixWorldZ);
		
		D3DXMatrixRotationX(&MatrixWorldX, fx);
		D3DXMatrixRotationY(&MatrixWorldY, fy);
		D3DXMatrixRotationZ(&MatrixWorldZ, fz);
		D3DXMatrixMultiply(&MatrixWorld, &MatrixWorldX, D3DXMatrixMultiply(&MatrixWorld, &MatrixWorldY, &MatrixWorldZ));
		pd3dDevice->SetTransform(D3DTS_WORLD, &MatrixWorld);
	}
	bool RenderGlobal(D3DCOLOR Color)//---------------------  Render -----------------------------------*/ 
	{
		if(pd3dDevice == NULL) return false;
		HRESULT			res;
		
		res = pd3dDevice->SetRenderTarget(0, Surface_Monitor);
		res = pd3dDevice->BeginScene();
		{
			res = pd3dDevice->Clear(	0, 
								NULL,
								D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
								Color, 1.0f, 0);

			res = pd3dDevice->SetFVF				( D3DFVF_CUSTOMVERTEX );
			res = pd3dDevice->SetStreamSource		( 0, g_pVB, 0, sizeof(CUSTOMVERTEX));

			//	Matrix
			//SetMatrixWorld					(0, 0, 0);
			pd3dDevice->SetTransform		(D3DTS_WORLD, &MatrixWorld);
			Camera.ApplyView				(pd3dDevice);
			Camera.ApplyProjection			(pd3dDevice);
			Camera.CameraCubMove();

			DWORD							Light_Enable = NULL;
			pd3dDevice->GetRenderState		(D3DRS_LIGHTING, &Light_Enable);
			if(Light_Enable)
			{
				for(UINT q = 0; q < Lights.size(); q++)
				{
					pd3dDevice->SetLight	(q, &Lights[q]);
					pd3dDevice->LightEnable	(q, true);
				}
			}


			for(UINT q=0; q<Rectangles.size(); q++)
			{
				if(Light_Enable)	pd3dDevice->SetMaterial	(&Materials[q]);
				if(FAILED(pd3dDevice->SetTexture	(0,	StaticTextures[q])))		return false;
				if(FAILED(pd3dDevice->DrawPrimitive	(D3DPT_TRIANGLELIST, q*6, 2)))	return false;
			}
			
			for(UINT q=0; q<UI.size(); q++)
				if(!UI[q]->Render(pd3dDevice, Light_Enable))						return false;

			for(UINT q=0; q<Text.size(); q++)
				Text[q].Draw();
		}
		res = pd3dDevice->EndScene();
		res = pd3dDevice->Present( NULL, NULL, NULL, NULL );

		return true;
	}
	virtual bool User_KeyboardScanner() = 0;

/*----------------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------------*/
public:
/*------------------------------------Constructors----------------------------------*/
	DirectX()
	{
		pD3D				=	NULL;
		pd3dDevice			=	NULL;
		Surface_Monitor		=	NULL;
		g_pVB				=	NULL;
		g_pIB				=	NULL;
		General_Input		=	NULL;
	}
	DirectX(HWND hWnd,HINSTANCE hInst_, bool Windowed, bool Light_Enable, bool Enable_Super_Light, UINT BackBufferCount, UINT MultiSampleType, UINT TextDetal, UINT MaxAnisotropi)
	{
		hInst				=	hInst_;
		pD3D				=	NULL;
		pd3dDevice			=	NULL;
		Surface_Monitor		=	NULL;
		g_pVB				=	NULL;
		g_pIB				=	NULL;
		General_Input		=	NULL;

		initD3D();
		initDisplay();
		initD3Present_Parameters(Windowed,BackBufferCount,hWnd,MultiSampleType);
		initDirect3D(Light_Enable, Enable_Super_Light, TextDetal, MaxAnisotropi);
		initD3DCamera();
		pd3dDevice->GetRenderTarget(0, &Surface_Monitor);
		
		Text.push_back(*new D3DXText(pd3dDevice, L"Blue"));
	}
/*----------------------------------------------------------------------------------*/

/*---------------------------------------Methods------------------------------------*/
	
	virtual bool Render() = 0;
	
	bool  KeyboardScanner()
	{
		bool result	=	false;
		Keyboard->GetDeviceState(sizeof(keyboard),keyboard);
		
		result		=	User_KeyboardScanner();
		if(keyboard	[DIK_LEFT]		&0x80)		{result = true;}
		if(keyboard	[DIK_RIGHT]		&0x80)		{result = true;}
		if(keyboard	[DIK_UP]		&0x80)      {result = true;}
		if(keyboard	[DIK_DOWN]		&0x80)		{result = true;}
		if(keyboard	[DIK_ESCAPE]	&0x80)		
		{
			result = true;
			DWORD RenderState;
			pd3dDevice->GetRenderState(D3DRS_FILLMODE, &RenderState);
			if(RenderState == D3DFILL_WIREFRAME)	RenderState = D3DFILL_SOLID;
			else									RenderState = D3DFILL_WIREFRAME;
			pd3dDevice->SetRenderState(D3DRS_FILLMODE,  RenderState);
		}


		if(keyboard	[DIK_W]			&0x80)      {result = true;}
		if(keyboard	[DIK_A]			&0x80)      {result = true;}
		if(keyboard	[DIK_S]			&0x80)      {result = true;}
		if(keyboard	[DIK_D]			&0x80)      {result = true;}
		if(keyboard	[DIK_Q]			&0x80)      {result = true;}
		if(keyboard	[DIK_E]			&0x80)      {result = true;}

		if(keyboard	[DIK_J]			&0x80)      {result = true;}
		if(keyboard	[DIK_K]			&0x80)      {result = true;}

		return result;
	}
	POINT MouseScanner()
	{
		POINT		coord;
		RECT		rect,
					rect2;

		GetWindowRect			(d3dpp.hDeviceWindow, &rect);
		GetClientRect			(d3dpp.hDeviceWindow, &rect2);
		GetCursorPos			(&coord);

		coord.x		-=		(rect.right		-	rect2.right);
		coord.y		-=		(rect.bottom	-	rect2.bottom);

		Mouse->GetDeviceState	(sizeof(DIMOUSESTATE), (LPVOID)&mouse);

		return coord;
	}
	void  MouseWheel(bool Z_Minus)
	{
		Camera.MouseWheel(Z_Minus);
	}
	int   MouseMove()
	{
		D3DXVECTOR3				pos,
								dir;

		POINT					point;

		point	=	MouseScanner();

		int						result	=	-1;
		
		D3D_UI::TransformCoords(pd3dDevice, Camera, MatrixWorld, pos, dir, point.x, point.y);

		for(UINT q=0; q<UI.size(); q++)
		{
			bool select = UI[q]->Select(pos, dir);
			UI[q]->MouseMove(select, this);
			if(select)
				result = q;
		}

		return result;
	}
	void  MouseDown()
	{
		int						index	=	MouseMove();
		if(index == -1)			return;
		UI[index]->MouseDown();
	}
	void  MouseUp()
	{
		D3DXVECTOR3				pos,
								dir;

		POINT					point;

		point	=	MouseScanner();

		int						result	=	-1;
		
		D3D_UI::TransformCoords(pd3dDevice, Camera, MatrixWorld, pos, dir, point.x, point.y);

		for(UINT q=0; q<UI.size(); q++)
		{
			bool select = UI[q]->Select(pos, dir);
			UI[q]->MouseUp(select, this);
		}
	}

/*----------------------------------------------------------------------------------*/

/*--------------------------------------DeStructor----------------------------------*/
	~DirectX()
	{
		for(UINT q=0;q<StaticTextures.size();q++)
		{
			if(StaticTextures[q] != NULL)
			{
				StaticTextures[q]->Release();
				StaticTextures[q] = NULL;
			}
		}
		StaticTextures.	clear();
		Materials.		clear();
		Lights.			clear();
		UI.				clear();
		Rectangles.		clear();


		if(NULL!=pD3D)				{pD3D->Release();				pD3D			= NULL;}
		if(NULL!=pd3dDevice)		{pd3dDevice->Release();			pd3dDevice		= NULL;}
		if(NULL!=Surface_Monitor)   {Surface_Monitor->Release();	Surface_Monitor = NULL;}
		if(NULL!=g_pIB)				{g_pIB->Release();				g_pIB			= NULL;}
		if(NULL!=g_pVB)				{g_pVB->Release();				g_pVB			= NULL;}
		if(NULL!=General_Input)		{General_Input->Release();		General_Input	= NULL;}
		if(NULL!=Keyboard)			{Keyboard->Unacquire();Keyboard->Release(); Keyboard = NULL;}
		if(NULL!=Mouse)				{Mouse->Unacquire();   Mouse->Release();	Mouse    = NULL;}
	}
/*----------------------------------------------------------------------------------*/
};
